package org.example.netty.test.nio.netty.chat.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;
import org.example.netty.test.nio.netty.chat.bean.LoginMessage;
import org.example.netty.test.nio.netty.chat.bean.AbsMessageBase;
import org.example.netty.test.nio.util.SerializeUtils;

import java.util.List;

/**
 * @author zp
 * @version 1.0
 * @description: 可共享的消息主题类
 * @date 2023/4/1 15:42
 */
@Slf4j
@ChannelHandler.Sharable
public class MyAgreeOnMessageCodecShared extends MessageToMessageCodec<ByteBuf, AbsMessageBase> {
    @Override
    protected void encode(ChannelHandlerContext ctx, AbsMessageBase msg, List<Object> out) throws Exception {
        ByteBuf outByteBuf = ctx.alloc().buffer();
        // 写入两个字节的魔数
        outByteBuf.writeInt(msg.getMagicNumber());
        // 协议版本号 一个字节
        outByteBuf.writeInt(msg.getVersion());
        // 序列化协议 一个字节
        outByteBuf.writeInt(msg.getSerializationAlgorithm());
        // 消息类型 一个字节
        outByteBuf.writeInt(msg.getMessageType());
        // 消息状态 一个字节
        outByteBuf.writeInt(msg.messageTypeStatus());
        // 保留字段
        outByteBuf.writeInt(99);
        // 获取使用JDK 序列化之后字节
        byte[] data = SerializeUtils.serialize(msg);
        // 写入四个字节的消息长度
        assert data != null;
        outByteBuf.writeInt(data.length);
        // 写入消息
        outByteBuf.writeBytes(data);
        // 加入数组方便后续调用
        out.add(outByteBuf);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        // 获取魔数
        int magicNumber = msg.readInt();
        // 获取版本号
        int version = msg.readInt();
        // 获取序列化类型
        int serializationAlgorithm = msg.readInt();
        // 获取消息类型
        int messageType = msg.readInt();
        // 获取状态
        int status = msg.readInt();
        // 保留字段
        int continueInt = msg.readInt();
        // 获取消息长度
        int length = msg.readInt();
        byte[] messageBytes = new byte[length];
        msg.readBytes(messageBytes);
        LoginMessage logMessage = SerializeUtils.deserialize(messageBytes, LoginMessage.class);
        // 加入队列方便后续使用
        out.add(logMessage);
        log.info("收到消息:{}", logMessage);
        log.info("{},{},{},{},{}.{},{}", magicNumber,version,serializationAlgorithm,messageType,status,continueInt,length);
    }
}
